/*
	QUBE
	Sandra Obermann - QPT 1 - 2012
	fhs33730 - 1110601021
	FH Salzburg - Studiengang MultiMediaTechnolgy
*/

// Cinder Basic Includes
#include "cinder/ImageIo.h"
#include "cinder/Utilities.h"

// Cinder Audio Includes
#include "cinder/audio/Io.h"
#include "cinder/audio/Output.h"
#include "../include/Resources.h"

// Own written Includes
#include "../include/DataManager.h"

// Used namespaces
using namespace ci;
using namespace ci::app;
using namespace ci::gl;
using namespace std;

// My QubeApp Class derived from AppBasic in Cinder to create the App
class QubeApp : public AppBasic
{
public:

	// Default Destructor for QubeApp element
	~QubeApp();

	// QubeApp Methods
	void setup();
	void update();
	void draw();

	void keyDown( KeyEvent event );
	void resize( ResizeEvent event );

private:

	// Add Colors for the flashing QUBE
	void addColorsToDataManager();

	// Play Background Sound
	void soundSetup();

	// Game Data Manager
	DataManager*		m_DataManager;

	// Sound Variable
	audio::SourceRef	m_audioSource;
};

// Destructor for QubeApp element which calls killLevel and deletes the QUBE
QubeApp::~QubeApp()
{
	if( m_DataManager )
	{
		m_DataManager->killLevel();
	}
}

// Initialize the QupeApp
void QubeApp::setup()
{
	// set zero to avoid errors
	m_DataManager = 0 ;
	
	// Start Game in full screen
	setFullScreen( true );

	// Get DataManager Reference
	m_DataManager = DataManager::getInstance();
	m_DataManager->initFonts();
	m_DataManager->buildLevel();

	// Init Color Array
	addColorsToDataManager();

	// Init Qube
	m_DataManager->setupQube();

	// Setup camera
	m_DataManager->setupCamera();

	// Initialize Sound
	soundSetup();
}

void QubeApp::keyDown( KeyEvent event )
{
	// Exit Game when ESC was pressed
	if(event.getCode() == KeyEvent::KEY_ESCAPE)
	{
		this->quit();
	}
	// Restart game with N
	else if(event.getCode() ==  KeyEvent::KEY_n)
	{
		m_DataManager->resetGame();
	}
	// or move the qube
	else if(!m_DataManager->isGameFinished() && !m_DataManager->isGameOver())
	{
		switch ( event.getCode() )
		{
			case KeyEvent::KEY_w:
			case KeyEvent::KEY_UP:
			{
				m_DataManager->moveQubeToDir(E_QUBE_MOVE_UP);
			}
			break;
			case KeyEvent::KEY_s:
			case KeyEvent::KEY_DOWN:
			{
				m_DataManager->moveQubeToDir(E_QUBE_MOVE_DOWN);
			}
			break;
			case KeyEvent::KEY_a:
			case KeyEvent::KEY_LEFT:
			{
				m_DataManager->moveQubeToDir(E_QUBE_MOVE_LEFT);
			}
			break;
			case KeyEvent::KEY_d:
			case KeyEvent::KEY_RIGHT:
			{
				m_DataManager->moveQubeToDir(E_QUBE_MOVE_RIGHT);
			}	
			break;

			default:
			break;
		}
	}
}

// Update the QubeApp
void QubeApp::update()
{
	// Hide Mouse cursor in every frame
	hideCursor();

	// Show and update current game time in every frame
	m_DataManager->getTimer()->updateTime(getElapsedSeconds());
	
	// Update qube 
	m_DataManager->updateQube();

	// Check if level is finished
	m_DataManager->isFinishedLevel();

	// Update Camera
	m_DataManager->updateCamera();
}

// Draw complete QubeApp
void QubeApp::draw()
{
	// clear color and depth buffer
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

	gl::setMatrices( m_DataManager->getCameraPersp() );
	// this pair of lines is the standard way to clear the screen in OpenGL
	gl::clear( Color( 0.0f, 0.0f, 0.0f ) );

	m_DataManager->drawBackground();
	m_DataManager->drawLevel();
	m_DataManager->drawQube();
	
	// when game is over
	if(m_DataManager->isGameOver() )
	{
		m_DataManager->drawFont(E_FONT_GAMEOVER);
	}

	// when game is finished
	if( m_DataManager->isGameFinished() )
	{
		m_DataManager->drawFont(E_FONT_FINISHED);
	}

	// when game is running draw time
	if(!m_DataManager->isGameFinished()  && !m_DataManager->isGameOver())
	{
		m_DataManager->drawFont(E_FONT_GAMETIME);
	}
}

// when Window is resized enables need to be re-enabled
void QubeApp::resize( ResizeEvent event )
{
	if(m_DataManager)
	{
		m_DataManager->resizeCamera(event);
	}

	glShadeModel (GL_SMOOTH);							// set the shader to smooth shader
	glEnable(GL_COLOR_MATERIAL);						// enable the material color
	glEnable(GL_ALPHA);									// enable the alpha
	glEnable(GL_BLEND);									// enable blend function
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);	// enable transparency

	// Light
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);

	// GL Point Size
	glPointSize( 2.0f );
}

// Add QUBE Colors to Color Array
void QubeApp::addColorsToDataManager()
{
	m_DataManager->addQubeColor( Color( 0.0f, 1.0f, 0.0f ) );	// Green
	m_DataManager->addQubeColor( Color( 1.0f, 1.0f, 0.0f ) );	// Yellow
	m_DataManager->addQubeColor( Color( 1.0f, 0.4f, 0.0f ) );	// Orange
	m_DataManager->addQubeColor( Color( 1.0f, 0.0f, 1.0f ) );	// Magenta
	m_DataManager->addQubeColor( Color( 0.6f, 0.0f, 0.8f ) );	// Violet
	m_DataManager->addQubeColor( Color( 0.2f, 0.4f, 1.0f ) );	// Light Blue
	m_DataManager->addQubeColor( Color( 0.0f, 0.8f, 1.0f ) );	// Cyan
}

// Load Background Sound file from Resource and play it
void QubeApp::soundSetup()
{
	m_audioSource = audio::load( loadResource( RES_HAPPY ) );
	audio::Output::play( m_audioSource );
}

// This line tells Flint to actually create the application
CINDER_APP_BASIC( QubeApp, RendererGl )